package qqserver.service;

import qqcommon.Message;
import qqcommon.MessageType;
import qqcommon.User;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 该类的一个对象和某个客户端保持通信
 */
public class ServerConnectClientThread extends Thread {
    private Socket socket;
    private String userId;//连接到服务器的用户id

    //离线消息
    private static ConcurrentHashMap<String, ArrayList<Message>> offlineDb = new ConcurrentHashMap<>();

    public ServerConnectClientThread(Socket socket, String userId) {
        this.socket = socket;
        this.userId = userId;
    }

    public Socket getSocket() {
        return socket;
    }

    @Override
    public void run() {//这里线程处于运行状态，可以发送/接收信息
        while (true) {
            try {
                System.out.println("服务端和客户端用户 " + userId + " 保持通信，读取数据。。。");
                ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                Message message = (Message) ois.readObject();
                //根据message的类型，做相应的业务处理
                if (message.getMesType().equals(MessageType.MESSAGE_GET_ONLINE_FRIEND)) {
                    //客户端需要在线用户列表
                    System.out.println(message.getSender() + "需要在线用户列表");
                    String onlineUser = ManageClientThread.getOnlineUser();
                    //创建一个Message对象，返回给客户端
                    Message message2 = new Message();
                    message2.setMesType(MessageType.MESSAGE_RETURN_ONLINE_FRIEND);
                    message2.setContent(onlineUser);
                    message2.setGetter(message.getSender());
                    //返回给客户端
                    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                    oos.writeObject(message2);
                } else if (message.getMesType().equals((MessageType.MESSAGE_TO_ALL_MES))) {
                    // 群发消息
                    // 使用迭代器遍历合法用户集合
                    Iterator<String> iterator = QQServer.getValidUsers().keySet().iterator();
                    while (iterator.hasNext()) {
                        String userId = iterator.next();
                        // 排除群发消息的发送者自己
                        if (!userId.equals(message.getSender())) {

                            if (ManageClientThread.getHashMap().containsKey(userId)) {
                                // 用户在线，进行转发
                                ObjectOutputStream oos = new ObjectOutputStream(
                                        ManageClientThread.getServerConnectClientThread(userId).
                                                getSocket().getOutputStream());
                                oos.writeObject(message);
                            } else {
                                // 用户不在线，将消息存储到offlineDb
                                offlineDb.putIfAbsent(userId, new ArrayList<>());
                                offlineDb.get(userId).add(message);
                                System.out.println("用户 " + userId + " 不在线，消息已存储到离线消息数据库中。");
                            }
                        }
                    }
                } else if (message.getMesType().equals((MessageType.MESSAGE_COMM_MES))) {
                    //私聊
                    if (QQServer.isUserExists(message.getGetter())) {
                        if (isUserOnline(message.getGetter())) {
                            //根据message获取getterId,然后得到对应线程
                            ServerConnectClientThread serverConnectClientThread =
                                    ManageClientThread.getServerConnectClientThread(message.getGetter());
                            //得到对应socket对象输出流，将message对象转发给指定的客户端
                            ObjectOutputStream oos = new ObjectOutputStream(
                                    serverConnectClientThread.getSocket().getOutputStream());
                            oos.writeObject(message);//转发，如果指定的客户不在线，可以选择保存到数据库，做成离线消息
                        } else {
                            // 如果用户不在线，将消息存储到offlineDb
                            offlineDb.putIfAbsent(message.getGetter(), new ArrayList<>());
                            offlineDb.get(message.getGetter()).add(message);
                            System.out.println("用户 " + message.getGetter() + " 不在线，消息已存储到离线消息数据库中。");
                        }
                    }
                } else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)) {
                    //发送文件
                    if (QQServer.isUserExists(message.getGetter())) {
                        if (isUserOnline(message.getGetter())) {
                            //根据getterId获取到对应的线程，将message转发
                            ObjectOutputStream oos = new ObjectOutputStream(
                                    ManageClientThread.getServerConnectClientThread(
                                            message.getGetter()).getSocket().getOutputStream());
                            oos.writeObject(message);
                        } else {
                            // 如果用户不在线，将消息存储到offlineDb
                            offlineDb.putIfAbsent(message.getGetter(), new ArrayList<>());
                            offlineDb.get(message.getGetter()).add(message);
                            System.out.println("用户 " + message.getGetter() + " 不在线，消息已存储到离线消息数据库中。");
                        }
                    }
                } else if (message.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT)) {
                    //客户端退出
                    System.out.println(message.getSender() + "退出");
                    //将这个客户端对应的线程从集合中删除
                    ManageClientThread.removeServerConnectClientThread(message.getSender());
                    socket.close();//关闭当前客户端的连接
                    //退出线程
                    break;
                } else if (message.getMesType().equals(MessageType.MESSAGE_REGISTER)) {
                    //注册账号
                    User newUser = message.getUser();
                    Message response = new Message();
                    if (!QQServer.isUserExists(newUser.getUserId())) {
                        QQServer.addUser(newUser);
                        response.setMesType(MessageType.MESSAGE_REGISTER_SUCCEED);
                    } else {
                        response.setMesType(MessageType.MESSAGE_REGISTER_FAIL);
                    }
                    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
                    oos.writeObject(response);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    // 检查用户是否在线
    private boolean isUserOnline(String getterId) {
        return ManageClientThread.getServerConnectClientThread(getterId) != null;
    }

    // 用户登录时发送离线消息
    public static void sendOfflineMessages(String userId) {
        if (offlineDb.containsKey(userId)) {
            ArrayList<Message> messages = offlineDb.get(userId);
            try {
                for (Message message : messages) {
                    //注意！循环发送所有留言，每次发送都需要 new 一次
                    ObjectOutputStream oos = new ObjectOutputStream(
                            ManageClientThread.getServerConnectClientThread(userId).
                                    getSocket().getOutputStream());
                    oos.writeObject(message);
                }
                offlineDb.remove(userId); // 发送完离线消息后，清空该用户的离线消息
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}
